class File
{
	enum e_open_type
	{
		FILE_OPEN_READ = GENERIC_READ,
		FILE_OPEN_WRITE = GENERIC_WRITE
	};

	enum e_seek_type
	{
		SEEK_BEGIN = FILE_BEGIN,
		SEEK_CURRENT = FILE_CURRENT, 
		SEEK_END = FILE_END 
	};
private:
	HANDLE hFile_;

	File(const string& file_name)
	{
		;
	}
public:
	File() : hFile_(INVALID_HANDLE_VALUE)
	{
		;
	}

	BOOL Open(const string& file_name, e_open_type op_type)
	{
		if (op_type == GENERIC_WRITE)
		{
			hFile_ = CreateFile(file_name.c_str,           // create MYFILE.TXT 
				GENERIC_WRITE,                // open for writing 
				0,                            // do not share 
				NULL,                         // no security 
				CREATE_ALWAYS,                // overwrite existing 
				FILE_ATTRIBUTE_NORMAL |       // normal file 
				FILE_FLAG_OVERLAPPED,         // asynchronous I/O 
				NULL);
		}
		else
		{
			hFile_ = CreateFile(file_name.c_str(),           // open MYFILE.TXT 
				GENERIC_READ,              // open for reading 
				FILE_SHARE_READ,           // share for reading 
				NULL,                      // no security 
				OPEN_EXISTING,             // existing file only 
				FILE_ATTRIBUTE_NORMAL,     // normal file 
				NULL);
		}

		return hFile_ != INVALID_HANDLE_VALUE;
	}

	BOOL Length(__int64* file_size)
	{
		if (INVALID_HANDLE_VALUE == hFile_ || NULL == file_size) return FALSE;

		DWORD dwHighSize = 0;
		*file_size = ::GetFileSize(hFile_, &dwHighSize);
		if (dwHighSize > 0)
			*file_size += (__int64)dwHighSize << 32;

		return TRUE;
	}

	BOOL Write(const byte* buffer, UINT len, UINT& dwWrite)
	{
		if (NULL == buffer || INVALID_HANDLE_VALUE == hFile_)
			return FALSE;

		return ::WriteFile(hFile_, (LPVOID)buffer, len, &dwWrite, NULL);
	}

	BOOL Read(byte* buffer, UINT len, UINT& dwRead)
	{
		if (NULL == buffer || INVALID_HANDLE_VALUE == hFile_)
			return FALSE;

		return !::ReadFile(hFile_, (LPVOID)buffer, 4, &dwRead, NULL);
	}

	BOOL Seek(__int64 offset, e_seek_type seek_type = SEEK_CURRENT)
	{
		if (INVALID_HANDLE_VALUE == hFile_)
			return FALSE;

		 LONG lLowSeek = (LONG)(offset & 0xffffffff);
		 LONG lHighSeek = (LONG)((offset & 0xffffffff00000000) >> 32);

		 DWORD dwError = NO_ERROR;
		 DWORD dwPtr = SetFilePointer(hFile_, lLowSeek, lHighSeek, seek_type); 

		 return !(dwPtr == INVALID_SET_FILE_POINTER && (lHighSeek == NULL || 
			 (dwError = GetLastError() != NO_ERROR)));
	}
		 
	~File()
	{
		if (INVALID_HANDLE_VALUE != hFile_)
			CloseHandle(hFile_);

		hFile_ = INVALID_HANDLE_VALUE;
	}
};
